#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/msg.h>
#include "../md5/md5.c"
#include "../DES/des.c"
#include "MsgType.h"

ClientInfo isExist(char *clientID);
// Step1 收到用户名并检查
ClientInfo ReceiveFromClient();
// Step2 用Hash密码加密K_TGS生成消息A
void CreatMsgA(MsgA *msgA, char *userPassword, char *K_CT);
// Step3 用K_TGS加密消息B
void CreatMsgB(MsgB *msgB, char *K_CT, ClientInfo clientInfo, char *K_TGS);
// Step4 发送消息
void SendToClient(MsgA msgA, MsgB msgB);

int main()
{
    int i;
    ClientInfo clientInfo;
    clientInfo.clientAddr = "empty";
    while (1)
    {
        clientInfo = ReceiveFromClient();
        if(clientInfo.clientAddr != "empty"){
            break;
        }
    }
    char *K_CT = "Client/TGS Session Key";   // Client/TGS会话密钥(Client/TGS Session Key)
    char *K_TGS = "TGS's secret key"; // TGS密钥(TGS's secret key)
    MsgA msgA;
    MsgAInit(&msgA);
    MsgB msgB;
    MsgBInit(&msgB);

    CreatMsgA(&msgA, clientInfo.clientPass, K_CT);
    CreatMsgB(&msgB, K_CT, clientInfo, K_TGS);
    
    SendToClient(msgA, msgB);
    exit(EXIT_SUCCESS);
}

ClientInfo isExist(char *clientID)
{
    ClientInfo clientInfo;
    // 检查用户数据库
    FILE *fp = NULL;
    char buf[BUFSIZ];
    char *token = "";
    if ((fp = fopen("user.txt", "r")) == NULL)
    {
        perror("fail to read");
        exit(1);
    }
    while (fgets(buf, BUFSIZ, fp) != NULL)
    {
        int len = strlen(buf);
        if (strstr(buf, clientID))
        {
            char part[2] = " ";
            token = strtok(buf, part);
            clientInfo.clientID = token;
            token = strtok(NULL, part);
            clientInfo.clientPass = token;
            token = strtok(NULL, part);
            clientInfo.clientAddr = token;
            break;
        }
        else
        {
            token = NULL;
        }
    }
    fclose(fp);
    return clientInfo;
}

// Step1 收到用户名并检查
ClientInfo ReceiveFromClient()
{
    char clientID[BUFSIZ];
    struct msg_st data;
    long int msgtype = 0;
    //建立消息队列
    int msgid = msgget((key_t)111, 0666 | IPC_CREAT);
    if (msgid == -1)
    {
        perror("msgget failed");
        exit(EXIT_FAILURE);
    }

    if (msgrcv(msgid, (void *)&data, BUFSIZ, msgtype, 0) == -1)
    {
        perror("msgcrv failed");
        exit(EXIT_FAILURE);
    }
    strcpy(clientID, data.text);

    // 删除消息队列
    if (msgctl(msgid, IPC_RMID, 0) == -1)
    {
        perror("msgclt failed");
        exit(EXIT_FAILURE);
    }
    ClientInfo clientInfo;
    clientInfo = isExist(clientID);
    if (clientInfo.clientPass == NULL)
    {
        printf("......\n该用户不存在\n\n");
        exit(1);
    }
    else
    {
        printf("......\n该用户存在数据库\n");        
    }    
    return clientInfo;
}

// Step2 用Hash密码加密K_TGS生成消息A
// 参数：消息A、用户口令、会话密钥
void CreatMsgA(MsgA *msgA, char *userPassword, char *K_CT)
{
    char *hashPassword = MD5Encryption(userPassword);
    GenerateSubKey(hashPassword);
    char *EnK_CT;
    EnK_CT = (char *)malloc(16 *sizeof(char));
    EnK_CT = EncryptionBS(K_CT, hashPassword);
    strcpy(msgA->K_CT, EnK_CT);
}

// Step3 用K_TGS加密消息B
void CreatMsgB(MsgB *msgB, char *K_CT, ClientInfo clientInfo, char *K_TGS)
{
    //GenerateSubKey(K_TGS);
    msgB->clientID = EncryptionBS(clientInfo.clientID, K_TGS);
    msgB->clientAddr = EncryptionBS(clientInfo.clientAddr, K_TGS);
    char *vaildity = "5 minutes";
    msgB->vaildity = EncryptionBS(vaildity, K_TGS);
    msgB->K_CT = EncryptionBS(K_CT, K_TGS);
}

// 发送消息
void SendToClient(MsgA msgA, MsgB msgB)
{
    struct msg_st data;
    long int msgtype = 0;
    //建立消息队列
    int msgid = msgget((key_t)112, 0666 | IPC_CREAT);
    if (msgid == -1)
    {
        perror("msgget failed");
        exit(EXIT_FAILURE);
    }

    data.msg_type = 1;
    strcpy(data.text, msgA.K_CT);
    if(msgsnd(msgid, (void*)&data, BUFSIZ, 0) == -1)  
    {  
        perror("msgsnd failed\n");
        exit(EXIT_FAILURE);  
    }

    strcpy(data.text, msgB.clientID);
    if(msgsnd(msgid, (void*)&data, BUFSIZ, 0) == -1)  
    {  
        perror("msgsnd failed\n");
        exit(EXIT_FAILURE);  
    }

    strcpy(data.text, msgB.clientAddr);
    if(msgsnd(msgid, (void*)&data, BUFSIZ, 0) == -1)  
    {  
        perror("msgsnd failed\n");
        exit(EXIT_FAILURE);  
    }
    strcpy(data.text, msgB.vaildity);
    if(msgsnd(msgid, (void*)&data, BUFSIZ, 0) == -1)  
    {  
        perror("msgsnd failed\n");
        exit(EXIT_FAILURE);  
    }
    strcpy(data.text, msgB.K_CT);
    if(msgsnd(msgid, (void*)&data, BUFSIZ, 0) == -1)  
    {  
        perror("msgsnd failed\n");
        exit(EXIT_FAILURE);  
    }
    printf("......\n发送消息A和消息B到客户机\n");   
}